<?php
namespace App\Services\Trade\Auth;

use Illuminate\Support\Facades\DB;
use App\Mappers\Trade\DemandMapper;
use App\Models\Base\UserModel;
use App\Models\Base\DistrictModel;
use App\Models\Trade\Shop\ShopModel;
use App\Models\Trade\Shop\ShopCountModel;
use App\Models\Trade\Demand\DemandModel;
use App\Models\Trade\Demand\DemandReportModel;
use App\Models\Trade\Demand\DemandCollectionModel;
use App\Models\Trade\Demand\DemandCountVisitModel;
use App\Models\Trade\Demand\DemandStatusModel;
use App\Models\Trade\Demand\DemandRejectModel;
use App\Models\Trade\Common\FishKindModel;
use App\Models\Trade\Common\FishUnitSizeModel;
use App\Models\Trade\Common\FishUnitPriceModel;
use App\Exceptions\Response\Service\ServiceException;
use App\Exceptions\Response\Service\ServiceCode;
use App\Services\Trade\SupplyService;
use App\Http\Requests\Trade\Demand\MyListRequest;

class DemandService
{

    /**
     * 数据拥有者检查
     *
     * @param int $id
     * @param int $userId
     * @return 0 | 1
     */
    public function isOwner($id, $userId)
    {
        $where[] = ['d.id', $id];
        $where[] = ['sp.user_id', $userId];
        
        return DemandModel::dbTable('d')
            ->leftJoin(ShopModel::TABLENAME . ' as sp', 'sp.id', '=', 'd.shop_id')
            ->where($where)
            ->count();
    }

    /**
     * 获取查询字段（列表）
     * 
     * @return string
     */
    protected function makeFieldList()
    {
        return implode(',', [
            'd.id,d.sn,d.shop_id,d.kind_id,fk.name as kind_name',
            'd.size_min,d.size_max,uz.name as size_unit_name',
            'd.price_type,d.price,up.name as price_unit_name,d.stock',
            'd.valided,d.created,d.updated,IFNULL(dc.pv,0) as pv'
        ]);
    }

    /**
     * 获取列表数据
     *
     * @param int $page 页码
     * @param int $pageSize 每页数量
     * @param int $status 状态
     * @param int $userId
     * @return array(\Illuminate\Support\Collection, int)
     */
    public function selectList($page, $pageSize, $status, $userId)
    {
        $queryList = DemandModel::dbTable('d');
        $queryCount = clone $queryList;
        $queryFields = $this->makeFieldList();

        $where[] = ['s.user_id', $userId];
        switch ($status) {
            // 上架
            case MyListRequest::STATUS_DEFAULT:
                $where[] = ['d.status', DemandModel::STATUS_DEFAULT];
                break;
            // 下架
            case MyListRequest::STATUS_LEAVE:
                $where[] = ['d.status', DemandModel::STATUS_LEAVE];
                $where[] = ['d.auditing', '<>', DemandModel::AUDITING_REJECT];
                // 下架原因
                $queryList->leftJoin(DemandStatusModel::TABLENAME . ' as ds', 'ds.demand_id', '=', 'd.id');
                $queryFields = $queryFields . ',ds.type as leave_type';
                break;
            // 被驳回
            case MyListRequest::STATUS_REJECT:
                $where[] = ['d.status', DemandModel::STATUS_LEAVE];
                $where[] = ['d.auditing', DemandModel::AUDITING_REJECT];
                break;
        }

        // 查询数量
        $count = $queryCount
            ->leftJoin(ShopModel::TABLENAME . ' as s', 's.id', '=', 'd.shop_id')
            ->where($where)
            ->count();
        // 查询数据
        $collection = $queryList->select(DB::raw($queryFields))
            ->leftJoin(FishKindModel::TABLENAME . ' as fk', 'fk.id', '=', 'd.kind_id')
            ->leftJoin(FishUnitSizeModel::TABLENAME . ' as uz', 'uz.id', '=', 'd.size_unit_id')
            ->leftJoin(FishUnitPriceModel::TABLENAME . ' as up', 'up.id', '=', 'd.price_unit_id')
            ->leftJoin(ShopModel::TABLENAME . ' as s', 's.id', '=', 'd.shop_id')
            ->leftJoin(DemandCountVisitModel::TABLENAME . ' as dc', 'dc.demand_id', '=', 'd.id')
            ->where($where)
            ->offset(($page - 1) * $pageSize)
            ->limit($pageSize)
            ->get();
        
        return array(
            $collection,
            $count
        );
    }

    /**
     * 获取最新驳回原因
     *
     * @param array $ids
     * @return \Illuminate\Support\Collection
     */
    public function selectRejectList($ids = [])
    {
        $sub = DemandRejectModel::dbTable()
            ->whereIn('demand_id', $ids)
            ->orderBy('created', 'desc');
    
        return DB::table( DB::raw("({$sub->toSql()}) as sub"))
            ->mergeBindings($sub)
            ->groupBy('demand_id')
            ->get();
    }
    
    /**
     * 获取编辑字段
     * 
     * @return string
     */
    protected function makeItemFields()
    {
        return implode(',', [
            'd.id,d.kind_id,fk.name as kind_name',
            'd.size_min,d.size_max,d.size_unit_id,uz.name as size_unit_name',
            'd.price_type,d.price,d.price_unit_id,up.name as price_unit_name,d.stock',
            'd.province,p.name as province_name,d.city,c.name as city_name',
            'd.area,a.name as area_name,d.town,t.name as town_name,d.address',
            'd.contact_name,d.contact_mobile,d.desc,d.desc_tag,d.logistics,d.valided'
        ]);
    }

    /**
     * 获取保存成功推荐列表
     *
     * @param int $id
     * @param int $pageSize
     * @throws ServiceException
     * @return array(\Illuminate\Support\Collection, int)
     */
    public function selectItemMoers($id, $pageSize = 5)
    {
        $item = DemandModel::findById($id, ['shop_id','kind_id'])->shift();
        // 求购统计
        $shopCount = ShopCountModel::findByShopId($item['shop_id'], ['demand_total','demand_pv'])->shift();
        // 出售列表
        $supplyService = new SupplyService();
        list ($collection, $count) = $supplyService->selectList(1, $pageSize, [
            'kind_id' => $item['kind_id']
        ]);
    
        return array(
            $collection,
            $shopCount
        );
    }
    
    /**
     * 获取编辑数据
     * 
     * @param int $id
     * @throws ServiceException
     * @return \Illuminate\Support\Collection
     */
    public function findItem($id)
    {
        $where[] = ['d.id', $id];
        return DemandModel::dbTable('d')->select(DB::raw($this->makeItemFields()))
            ->leftJoin(FishKindModel::TABLENAME . ' as fk', 'fk.id', '=', 'd.kind_id')
            ->leftJoin(FishUnitSizeModel::TABLENAME . ' as uz', 'uz.id', '=', 'd.size_unit_id')
            ->leftJoin(FishUnitPriceModel::TABLENAME . ' as up', 'up.id', '=', 'd.price_unit_id')
            ->leftJoin(DistrictModel::TABLENAME . ' as p', 'p.id', '=', 'd.province')
            ->leftJoin(DistrictModel::TABLENAME . ' as c', 'c.id', '=', 'd.city')
            ->leftJoin(DistrictModel::TABLENAME . ' as a', 'a.id', '=', 'd.area')
            ->leftJoin(DistrictModel::TABLENAME . ' as t', 't.id', '=', 'd.town')
            ->where($where)
            ->get();
    }

    /**
     * 保存数据
     *
     * @param \Illuminate\Http\Request $request
     * @param int $userId
     * @throws ServiceException
     * @return 1 | id
     */
    public function saveItem($request, $userId)
    {
        $id = $request->input('id');
        // 店铺
        $shopService = new ShopService();
        $shopId = $shopService->saveItem($request, $userId);
        // 数据映射
        $dataMapper = new DemandMapper($request->all());
        $data = $dataMapper->make()->toArray();
        // 创建
        if (! $id) {
            $data['shop_id'] = $shopId;
            $data['pub_user_id'] = $userId;
            if (! ($number = DemandModel::addItem($data))) {
                throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
            }
        }
        // 修改
        if ($id && ! ($number = DemandModel::editItem($id, $data))) {
            throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
        }

        // 抛出发布事件
        \App\Events\Trade\Demand\PublishEvent::dispatch($id, $shopId);
        
        return $number;
    }
    
    /**
     * 删除数据
     * 
     * @param int $id            
     * @throws ServiceException
     * @return boolean
     */
    public function banItem($id)
    {
        if (! ($number = DemandModel::banItem($id))) {
            throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
        }

        return (boolean) $number;
    }

    /**
     * 修改状态
     *
     * @param int $id
     * @param int $status
     * @throws ServiceException
     * @return boolean
     */
    public function editItemStatus($id, $status)
    {
        if (! ($number = DemandModel::editItemStatus($id, $status))) {
            throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
        }

        // 抛出下架事件
        if ($status == DemandModel::STATUS_LEAVE) {
            \App\Events\Trade\Demand\LeaveEvent::dispatch($id);
        }
        
        return (boolean) $number;
    }

    /**
     * 刷新数据
     *
     * @param int $id
     * @throws ServiceException
     * @return boolean
     */
    public function refreshItem($id)
    {
        if (! ($number = DemandModel::refreshItem($id))) {
            throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
        }

        // 抛出举报事件
        \App\Events\Trade\Demand\RefreshEvent::dispatch($id);
        
        return (boolean) $number;
    }

    /**
     * 举报数据
     *
     * @param int $id
     * @param int $userId
     * @throws ServiceException
     * @return boolean
     */
    public function reportItem($id, $userId)
    {
        if (DemandReportModel::findItem($userId, $id)->count()) {
            throw new ServiceException(ServiceCode::SERVICE_DATA_EXISTED);
        }
    
        if (! ($number = DemandReportModel::addItem($userId, $id))) {
            throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
        }

        // 抛出举报事件
        \App\Events\Trade\Demand\ReportEvent::dispatch($id);
        
        return (boolean) $number;
    }

    /**
     * 收藏数据/取消收藏
     *
     * @param int $id
     * @param int $type
     * @param int $userId
     * @throws ServiceException
     * @return boolean
     */
    public function collectionItem($id, $type, $userId)
    {
        // 存在检查
        if ($type == DemandCollectionModel::ACTION_TYPE_DEFAULT && DemandCollectionModel::findItem($userId, $id)->count()) {
            throw new ServiceException(ServiceCode::SERVICE_DATA_EXISTED);
        }
        // 添加收藏
        if ($type == DemandCollectionModel::ACTION_TYPE_DEFAULT && ! ($number = DemandCollectionModel::addItem($userId, $id))) {
            throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
        }
        // 不存在检查
        if ($type == DemandCollectionModel::ACTION_TYPE_DELETE && ! DemandCollectionModel::findItem($userId, $id)->count()) {
            throw new ServiceException(ServiceCode::SERVICE_DATA_NOT_EXIST);
        }
        // 删除收藏
        if ($type == DemandCollectionModel::ACTION_TYPE_DELETE && ! ($number = DemandCollectionModel::banItem($userId, $id))) {
            throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
        }
        
        // 抛出收藏事件
        \App\Events\Trade\Demand\CollectionEvent::dispatch($id, $type);

        return (boolean) $number;
    }
    
    /**
     * 批量删除收藏
     * 
     * @param array $ids
     * @param int $userId
     * @throws ServiceException
     * @return boolean
     */
    public function deleteCollection($ids, $userId)
    {
        // 统计批量自减
        if (! ($number = DemandCountVisitModel::decCollectionByDemandIds($ids, $userId))) {
            throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
        }
        // 收藏批量删除
        if (! ($number = DemandCollectionModel::banList($userId, $ids))) {
            throw new ServiceException(ServiceCode::SERVICE_ACTION_SAVE_ERROR);
        }

        return (boolean) $number;
    }

    /**
     * 获取查询字段（收藏列表）
     * 
     * @return string
     */
    protected function makeFieldCollectionList()
    {
        return implode(',', [
            'd.id,d.sn,d.shop_id,d.kind_id,fk.name as kind_name',
            'd.status,d.size_min,d.size_max,uz.name as size_unit_name',
            'd.price_type,d.price,up.name as price_unit_name,d.stock',
            'd.logistics,p.name as province_name,c.name as city_name',
            'd.contact_name,d.desc,d.desc_tag,d.created,d.updated',
            'u.avatar,s.verify_classify,s.verify_name,s.verify_type'
        ]);
    }
    
    /**
     * 获取收藏列表
     *
     * @param int $page 页码
     * @param int $pageSize 每页数量
     * @param int $userId
     * @return array(\Illuminate\Support\Collection, int)
     */
    public function selectCollectionList($page, $pageSize, $userId)
    {
        $queryList = DemandCollectionModel::dbTable('dd');
        $queryCount = clone $queryList;
        
        $where[] = ['dd.user_id', $userId];

        // 查询数量
        $count = $queryCount->where($where)->count();
        // 查询数据
        $collection = $queryList->select(DB::raw($this->makeFieldCollectionList()))
            ->leftJoin(DemandModel::TABLENAME . ' as d', 'd.id', '=', 'dd.demand_id')
            ->leftJoin(FishKindModel::TABLENAME . ' as fk', 'fk.id', '=', 'd.kind_id')
            ->leftJoin(FishUnitSizeModel::TABLENAME . ' as uz', 'uz.id', '=', 'd.size_unit_id')
            ->leftJoin(FishUnitPriceModel::TABLENAME . ' as up', 'up.id', '=', 'd.price_unit_id')
            ->leftJoin(DistrictModel::TABLENAME . ' as p', 'p.id', '=', 'd.province')
            ->leftJoin(DistrictModel::TABLENAME . ' as c', 'c.id', '=', 'd.city')
            ->leftJoin(ShopModel::TABLENAME . ' as s', 's.id', '=', 'd.shop_id')
            ->leftJoin(UserModel::TABLENAME . ' as u', 'u.id', '=', 's.user_id')
            ->where($where)
            ->orderBy('dd.created', 'desc')
            ->offset(($page - 1) * $pageSize)
            ->limit($pageSize)
            ->get();
        
        return array(
            $collection,
            $count
        );
    }
}